package com.sservice.web.controller.admin;

import com.sservice.common.Constants;
import com.sservice.common.SameUrlData;
import com.sservice.model.vo.OtherReceivablesLogVo;
import com.sservice.model.vo.OtherReceivablesVo;
import com.sservice.service.service.*;
import com.sservice.base.entity.dto.BaseResult;
import com.sservice.base.entity.dto.ListResult;
import com.sservice.base.entity.dto.Pagination;
import com.sservice.model.entity.Clientele;
import com.sservice.model.entity.OtherReceivables;
import com.sservice.urp.entity.User;
import com.sservice.web.log.Action;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by suweiming on 2017/12/20.
 */

@Controller
@RequestMapping("/admin/otherReceivables")
public class OtherReceivablesController {
    @Autowired
    private OtherReceivablesService service;
    @Autowired
    private OtherReceivablesLogService serviceLog;

    @Autowired
    private ISysLogService sysLogService;
    @Autowired
    private IClienteleService clienteleService;
    @Autowired
    private ExportService exportService;

    /***
     * 创建
     * @param arg
     * @return
     */
    @ResponseBody
    @SameUrlData
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public BaseResult<Integer> create(OtherReceivables arg, HttpSession session, HttpServletRequest request) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        User user = (User) session.getAttribute(Constants.USER);
        arg.setCreator(String.valueOf(user.getId()));
        Clientele clientele = clienteleService.selectByPrimaryKey(Integer.valueOf(arg.getClienteleId()));
        if (!("1".equals(clientele.getSupplierCheckStatus()) && "1".equals(clientele.getStatus()))) {
            return new BaseResult(false, "供应商未审核通过,不能下单!", 403);
        }
        int service_res = service.insertSelective(arg);
        if (service_res > 0) {
            sysLogService.log("创建", request, arg.getId(), arg.getType().equals("0") ? Action.otherReceiableType : Action.otherPayType);
        }
        BaseResult<Integer> res = new BaseResult<Integer>(true, service_res);
        return res;
    }

    /***
     * 详情
     * @param arg
     */
    @ResponseBody
    @RequestMapping(value = "/detail/{id}", method = RequestMethod.GET)
    public BaseResult get(OtherReceivables arg) {
        OtherReceivables or1 = service.selectByPrimaryKey(arg.getId());
        return new BaseResult(true, or1);
    }

    @ResponseBody
    @RequestMapping(value = "/hexiao/{id}", method = RequestMethod.GET)
    public BaseResult hexiao(OtherReceivables arg, HttpServletRequest request) {
        OtherReceivables or = new OtherReceivables();
        or.setId(arg.getId());
        or.setVerified("1");
        OtherReceivables or2 = service.selectByPrimaryKey(arg.getId());
        int or1 = service.updateByPrimaryKeySelective(or);
        if (or1 > 0) {
            sysLogService.log("核销", request, arg.getId(), or2.getType().equals("0") ? Action.otherReceiableType : Action.otherPayType);
        }
        return new BaseResult(true, or1);
    }

    /***
     * 其他应收明细删除
     * @param arg
     * @return
     */
    @SameUrlData
    @ResponseBody
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    public BaseResult delete(OtherReceivables arg) {
        OtherReceivables or1 = service.selectByPrimaryKey(arg.getId());
        if (or1.getAccountReceivables().compareTo(BigDecimal.valueOf(0.0)) == 0) {
            int or2 = service.deleteByPrimaryKey(arg.getId());// 删除
            return new BaseResult(true, or2);
        } else {
            return new BaseResult(false, (or1.getType().equals("1") ? "应收款已经收款" : "应付款已经付款") + "，不能删除", 403);
        }

    }

    /**
     * update
     *
     * @param arg
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public BaseResult<Integer> update(OtherReceivables arg) {
        int service_res = service.updateByPrimaryKeySelective(arg);
        BaseResult<Integer> res = new BaseResult<Integer>(true, service_res);
        return res;
    }

    /***
     * 申请开票
     * @param arg
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/applyPaper/{id}", method = RequestMethod.POST)
    public BaseResult applyPaper(OtherReceivables arg, HttpServletRequest request) {
        OtherReceivables or_ = service.selectByPrimaryKey(arg.getId());
        if (!"0".equals(or_.getPaperStatus())) {
            return new BaseResult(false, "应收款已申请发票", 403);
        }
        Clientele c = clienteleService.selectByPrimaryKey(Integer.valueOf(or_.getClienteleId()));
        if (c.getPaperBank() == null) {
            return new BaseResult(false, "客户未填写开票资料，不能申请发票!", 403);
        }
        OtherReceivables or1 = new OtherReceivables();
        or1.setPaperStatus("1");
        or1.setId(arg.getId());
        or1.setId(arg.getId());
        or1.setPaperStatus("1");
        or1.setPaperAddress(c.getPaperAddress());
        or1.setPaperAccount(c.getPaperAccount());
        or1.setPaperTel(c.getPaperTel());
        or1.setPaperUnitCode(c.getUnitCode());
        or1.setPaperCom(c.getComName());
        or1.setPaperBank(c.getPaperBank());

        int service_res = service.updateByPrimaryKeySelective(or1);
        if (service_res == 0) {
            return new BaseResult(false, "操作失败,请稍后再试!", 403);
        } else {
            sysLogService.log("申请开票", request, arg.getId(), Action.otherReceiableType);
        }
        return new BaseResult(true, service_res);
    }

    @SameUrlData
    @ResponseBody
    @RequestMapping(value = "/payByCash", method = RequestMethod.POST)
    public BaseResult payByCash(OtherReceivables arg, HttpServletRequest request) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        OtherReceivables or = service.selectByPrimaryKey(arg.getId());
        User user = (User) request.getSession().getAttribute(Constants.USER);
        BigDecimal receive = arg.getAccountReceivables();
        arg.setCreator(String.valueOf(user.getId()));
        arg.setName(or.getName());

        arg.setAccountReceivables(or.getAccountReceivables().add(arg.getAccountReceivables()));
        arg.setReceivables(receive);
        arg.setUnitCode(or.getUnitCode());
        int res = arg.getAccountReceivables().compareTo(or.getReceivables());
        if (res == 0) {
            arg.setVerified("1"); // 自动核销
            arg.setPaperStatus("1"); // 自动申请发票票
        } else if (res == 1) {
            return new BaseResult(false, service.payTypeStr(arg.getType()) + "款金额累计大于应收金额!", 403);
        }
        Object service_res = service.payByCash(arg);
        if (service_res instanceof String) {
            return new BaseResult<Integer>(false, service_res.toString(), 403);
        }
        int r = (int) service_res;
        if (r > 0) {
            sysLogService.log(service.payTypeStr(arg.getType()) + "款" + receive + ("1".equals(arg.getVerified()) ? ",并自动核销." : ".实际于" + arg.getActualPayTime() + "付款，备注" + arg.getRemark()),
                    request, arg.getId(), Action.otherReceiableType);
        }
        return new BaseResult<Integer>(true, r);
    }

    /**
     * 日志查询
     *
     * @param arg
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/log/query", method = RequestMethod.GET)
    public BaseResult<Integer> queryLog(OtherReceivablesLogVo arg) {
        List<OtherReceivablesLogVo> service_res = serviceLog.queryByPage(arg);
        int total = serviceLog.queryByCount(arg);
        Pagination page = new Pagination(arg.getPage(), total, arg.getSize());
        ListResult res = new ListResult(true, service_res);
        res.setPage(page);
        return res;
    }

    @ResponseBody
    @RequestMapping(value = "/query/{type}", method = RequestMethod.GET)
    public BaseResult<Integer> query(OtherReceivablesVo arg) {
        List<OtherReceivablesVo> service_res = service.queryByPage(arg);
        int total = service.queryByCount(arg);
        Pagination page = new Pagination(arg.getPage(), total, arg.getSize());
        ListResult res = new ListResult(true, service_res);
        res.setPage(page);
        return res;
    }


    public String getTypeStr(String type) {
        String typeStr = "";
        if (type.equals("0")) typeStr = "其他核销";
        if (type.equals("1")) typeStr = "待收发票明细";
        else typeStr = "其他应付明细";
        return typeStr;
    }

    public String getPaperStatus(String paperStatus) {
        return ("0".equals(paperStatus) || "1".equals(paperStatus)) ? "未收票" : ("2".equals(paperStatus) ? "部分收票" : ("3".equals(paperStatus) ? "完全收票" : ""));
    }

    /***
     * 1. 其他应付明细导出,
     * 2. 其他已付明细导出
     * 3. 其他应收明细导出
     * 4. 其他已收明细导出
     * @param arg
     * @return
     */
    @RequestMapping(value = "/export/{type}", method = RequestMethod.GET)
    public OutputStream export(OtherReceivablesVo arg, HttpServletRequest request, HttpServletResponse response) throws IOException {
        arg.setPage(0);
        arg.setSize(Integer.MAX_VALUE);
        List<OtherReceivablesVo> list = service.queryByPage(arg);
        ServletOutputStream outputStream = response.getOutputStream();
        String typeStr = getTypeStr(arg.getType());
        exportService.setResponseHeader(response, request, typeStr + "Excel");
        String hql = typeStr; // sheet 名称
        List<Map> lm = new ArrayList<Map>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < list.size(); i++) {
            Map map = new LinkedHashMap();
            OtherReceivablesVo ov = list.get(i);
            if ("0".equals(arg.getType())) {
                map.put("应收款名称", ov.getName());
                map.put("客户名称", ov.getClienteleName());
                map.put("统一信用代码", ov.getUnitCode());
                map.put("应收金额", ov.getReceivables());
                map.put("实收金额", ov.getAccountReceivables());
                if ("!3".equals(arg.getPaperStatus())) { //自定义待开、已开发票导出
                    map.put("已收票金额", ov.getPaperedNumber());
                    map.put("可收票金额", ov.getAccountReceivables().subtract(ov.getPaperedNumber()));
                    map.put("收票状态", getPaperStatus(ov.getPaperStatus()));
                } else {
                    map.put("收款日期", sdf.format(ov.getCreateAt()));
                }
            } else {
                map.put("应付款名称", ov.getName());
                map.put("供应商名称", ov.getClienteleName());
                map.put("统一信用代码", ov.getUnitCode());
                map.put("应付金额", ov.getReceivables());
                map.put("实付金额", ov.getAccountReceivables());
                if ("3".equals(arg.getPaperStatus())||"!3".equals(arg.getPaperStatus())) { //自定义待收、已收导出
                    map.put("已收票金额", ov.getPaperedNumber());
                    map.put("可收票金额", ov.getAccountReceivables().subtract(ov.getPaperedNumber()));
                    map.put("收票状态", getPaperStatus(ov.getPaperStatus()));
                }
            }
            map.put("创建人", ov.getUserName1());
            map.put("创建时间", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(ov.getCreateAt()));
            map.put("是否核销完毕", "1".equals(ov.getVerified()) ? "核销完毕" : "未核销完毕");
            map.put("备注", ov.getRemark());

            lm.add(map);
        }
        return exportService.exportExcel(hql, lm, outputStream);
    }

}
